import Vue from 'vue';
import App from '@component/index.vue';

const state = {};

let eventDriver = null;

const enableCrawler = () => {
	disableCrawler();
	
	state.vueApp = new Vue({render: h => h(App)});
	state.vueApp.serviceRefs = state.serviceRefs;
	state.vueApp.$mount();
	state.vueAppEle = state.vueApp.$el;
	document.body.appendChild(state.vueAppEle);
	
	eventDriver.emit('app-mount-event', state.vueAppEle);

	registerDomObserver();
	registerMouseListener();

};

const disableCrawler = () => {
	releaseDomObserver();
	releaseMouseListener();
	eventDriver.emit('app-mount-event', state.vueAppEle);
	if(state.vueApp){
		state.vueApp.$destroy();
		state.vueAppEle.remove();
		state.vueApp = null;
	}

};

const emitAppMsg = (name, data) => {
	if(state.vueApp){
		state.vueApp.$bus.$emit(name, data);
	}
};

const onMouseMove = (event) => handleMouseEvent('mousemove', event);
const onMouseClick = (event) => handleMouseEvent('mouseclick', event);
const onContextMenu = (event) => handleMouseEvent('contextmenu', event);
const onBeforeUnload = (event) => handlePageEvent('beforeUnload', event);
const onScroll = (event) => handleMouseEvent('scroll', event);
const addWinEvt = (name, callback, capture) => window.addEventListener(name, callback, capture);
const delWinEvt = (name, callback, capture) => window.removeEventListener(name, callback, capture);

const registerMouseListener = () => {
	releaseMouseListener();
	addWinEvt('click', onMouseClick, true);
	addWinEvt('mousemove', onMouseMove, true);
	addWinEvt('contextmenu', onContextMenu, false);
	addWinEvt('scroll', onScroll, false);
	//addWinEvt('beforeunload', onBeforeUnload, true);

};

const releaseMouseListener = () => {
	delWinEvt('click', onMouseClick, true);
	delWinEvt('mousemove', onMouseMove, true);
	delWinEvt('contextmenu', onContextMenu, false);
	delWinEvt('scroll', onScroll, false);
	///delWinEvt('beforeunload', onBeforeUnload, true);

};


const handelActionClick = (evtMsg) => {
	if(null == state.vueApp){
		enableCrawler();
		eventDriver.emit('msg-forward-event', {type: 'cmd', data: {name: 'action', data: {type: 'enable', color: 'red'}}});
		return;
	}
	disableCrawler();
	eventDriver.emit('msg-forward-event', {type: 'cmd', data: {name: 'action', data: {type: 'disable'}}});

};

const handleMouseEvent = (type, event) => {
	let target = event.target;
	if(null != target){
		state.vueApp.$bus.$emit('mouse-event', {event: event});
		return;
	}

};

const handlePageEvent = (type, event) => {
	event.preventDefault();
	event.returnValue = 'data not save, please save it!';

};

const observeConfig =  {
	subtree: true,
	childList: true,
	attributes: true,
	attributeOldValue: true,
	characterData: true,
	characterDataOldValue: true
};

const mutationCallback = (mutations, observer) => {
	eventDriver.emit('dom-mutations-event', mutations);

};

const observer = new MutationObserver(mutationCallback);

const registerDomObserver = () => {
	observer.observe(document, observeConfig);

};

const releaseDomObserver = () => {
	observer.disconnect();

};

const initSetup = (driver) => {
	eventDriver = driver;
	eventDriver.on('startup', (refs) => state.serviceRefs = refs);
	eventDriver.on('app-action-event', (evtMsg) => handelActionClick(evtMsg));
	eventDriver.on('dom-update-event', (deltaMap) => emitAppMsg('dom-update', deltaMap));

};

export default function(driver){
	initSetup(driver);
	return {
		enableCrawler: enableCrawler,
		disableCrawler: disableCrawler
	};

};